package com.tnxst.phexamination.room.dao;


import androidx.room.Dao;
import androidx.room.Delete;
import androidx.room.Insert;
import androidx.room.OnConflictStrategy;
import androidx.room.Query;
import androidx.room.RawQuery;
import androidx.room.Update;
import androidx.sqlite.db.SimpleSQLiteQuery;
import androidx.sqlite.db.SupportSQLiteQuery;

import java.lang.reflect.ParameterizedType;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import sun.dc.pr.PRError;

@Dao
public abstract class BaseDao<E> {

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    public abstract void insert(E... entity);

    @Update
    public abstract void update(E... entity);

    @Delete
    public abstract void delete(E... entity);

    @RawQuery
    protected abstract E doFindById(SupportSQLiteQuery query);

    @RawQuery
    protected abstract E doFindByField(SupportSQLiteQuery query);

    @RawQuery
    protected abstract List<E> doFindByFieldList(SupportSQLiteQuery query);

    @RawQuery
    protected abstract List<E> doFindAll(SupportSQLiteQuery query);

    @RawQuery
    protected abstract List<E> doFindByLike(SupportSQLiteQuery query);

    @RawQuery
    protected abstract E doFindByMap(SupportSQLiteQuery query);

    @RawQuery
    protected abstract List<E> dofindByLikeAndWhere(SupportSQLiteQuery query);

    public List<E> findByLikeAndWhere(String field, Object o, String key, Object value){
        String like = "%" + o.toString() + "%";
        SimpleSQLiteQuery query = new SimpleSQLiteQuery("SELECT * FROM " + getTableName()
                + " WHERE " + field + " like ? and " + key + " = ?", new Object[]{like,value});
        return dofindByLikeAndWhere(query);
    }

    public E findByMap(LinkedHashMap<String,Object> params){
        StringBuffer sql = new StringBuffer();
        sql.append("SELECT * FROM ").append(getTableName()).append(" WHERE ");
        Iterator<String> iterator = params.keySet().iterator();
        while (iterator.hasNext()){
            String next = iterator.next();
            sql.append(next).append(" = ?");
            if (iterator.hasNext())
                sql.append(" AND ");
        }
        SimpleSQLiteQuery query = new SimpleSQLiteQuery(sql.toString(), params.values().toArray());
        return doFindById(query);
    }

    public E findById(Integer id){
        SimpleSQLiteQuery query = new SimpleSQLiteQuery("SELECT * FROM " + getTableName() + " WHERE id = ?", new Object[]{id});
        return doFindById(query);
    }

    public E findByField(String field, Object value){
        SimpleSQLiteQuery query = new SimpleSQLiteQuery("SELECT * FROM " + getTableName() + " WHERE " + field +" = ?", new Object[]{value});
        return doFindByField(query);
    }

    public List<E> findAll(){
        SimpleSQLiteQuery query = new SimpleSQLiteQuery("SELECT * FROM " + getTableName() , new Object[]{});
        return doFindAll(query);
    }

    public List<E> findByLike(String field, Object value){
        String like = "%" + value.toString() + "%";
        SimpleSQLiteQuery query = new SimpleSQLiteQuery("SELECT * FROM " + getTableName() + " WHERE " + field + " like ?", new Object[]{like});
        return doFindByLike(query);
    }

    public List<E> findByFieldList(String field, Object value){
        SimpleSQLiteQuery query = new SimpleSQLiteQuery("SELECT * FROM " + getTableName() + " WHERE " + field +" = ?", new Object[]{value});
        return doFindByFieldList(query);
    }


    private String getTableName(){
        Class clazz = (Class)
                ((ParameterizedType) getClass().getSuperclass().getGenericSuperclass())
                        .getActualTypeArguments()[0];
        // tableName = StringUtil.toSnakeCase(clazz.getSimpleName());
        String tableName = clazz.getSimpleName();
        return tableName;
    }



}
